package com.weifly.weistock.record.bill.impl;

import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.record.RecordUtils;
import com.weifly.weistock.record.bill.BillMonitorService;
import com.weifly.weistock.record.bill.BillStoreService;
import com.weifly.weistock.record.bill.BillUtils;
import com.weifly.weistock.record.bill.CalcStockContext;
import com.weifly.weistock.record.bill.domain.GetStockRecordRequest;
import com.weifly.weistock.record.bill.domain.StockRecordDto;
import com.weifly.weistock.record.bill.domain.StockSummaryDto;
import com.weifly.weistock.record.option.OptionUtils;
import com.weifly.weistock.record.base.domain.MergeRecordResult;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 股票交易记录管理服务实现
 *
 * @author weifly
 * @since 2020/01/15
 */
public class BillMonitorServiceImpl implements BillMonitorService {

    private SortedMap<String, StockSummaryDto> stockMap = new TreeMap<>(); // key有序的map

    private BillStoreService billStoreService;

    public void setBillStoreService(BillStoreService billStoreService) {
        this.billStoreService = billStoreService;
    }

    @Override
    public MergeRecordResult mergeRecordList(List<StockRecordDto> recordList) {
        MergeRecordResult result = new MergeRecordResult();
        if(recordList==null || recordList.isEmpty()){
            return result;
        }

        Map<String, StockSummaryDto> modifyStockMap = new TreeMap<>(); // 被修改的股票集合
        result.setTotal(recordList.size());

        // 合并record到summary
        for(StockRecordDto recordDto : recordList){
            OptionUtils.checkEmpty(recordDto.getDate(), "发生日期不能为空");
            OptionUtils.checkEmpty(recordDto.getStockCode(), "证券代码不能为空");
            StockSummaryDto summaryDto = this.loadStockSummary(recordDto, modifyStockMap);
            BillUtils.addRecordToSummary(summaryDto, recordDto, result);
        }

        for(StockSummaryDto summaryDto : modifyStockMap.values()){
            // 交易记录排序
            RecordUtils.sortRecordList(summaryDto.getRecordList());
            // 计算盈亏
            this.calcOneStock(summaryDto);
            // 写入存储
            this.billStoreService.saveStockSummary(summaryDto);
            // 替换缓存
            this.stockMap.put(summaryDto.getStockCode(), summaryDto);
        }

        return result;
    }

    private StockSummaryDto loadStockSummary(StockRecordDto recordDto, Map<String, StockSummaryDto> modifyStockMap){
        StockSummaryDto summaryDto = modifyStockMap.get(recordDto.getStockCode());
        if(summaryDto==null){
            // 从xml中加载
            summaryDto = this.billStoreService.loadStockSummary(recordDto.getStockCode());
            if(summaryDto==null){
                // 库中没有，新创建
                summaryDto = new StockSummaryDto();
                summaryDto.setStockCode(recordDto.getStockCode());
                summaryDto.setStockName(recordDto.getStockName());
            }
            modifyStockMap.put(recordDto.getStockCode(), summaryDto);
        }
        return summaryDto;
    }

    public void calcOneStock(StockSummaryDto summaryDto){
        List<StockRecordDto> recordList = summaryDto.getRecordList();
        RecordUtils.clearRecordPair(recordList);

        CalcStockContext calcCtx = new CalcStockContext();
        for(int i=0;i<recordList.size();i++){
            StockRecordDto currRecord = recordList.get(i);
            // 处理卖出记录
            if(BillUtils.isCloseRecord(currRecord)){
                calcCtx.initRecord(currRecord);
                for(int j=i-1;j>=0;j--){
                    StockRecordDto preRecord = recordList.get(j);
                    calcCtx.buildPair(preRecord);
                    if(calcCtx.getCurrTradeNumber()<=0){
                        // 完成配对
                        break;
                    }
                }
                calcCtx.finishRecord();
            }
        }

        // 计算统计信息
        double diffAmount = 0;
        double feeService = 0;
        double feeStamp = 0;
        Integer afterNumber = null;
        for(int i=0;i<recordList.size();i++){
            StockRecordDto currRecord = recordList.get(i);
            if(currRecord.getDiffAmount()!=null){
                diffAmount = WeistockUtils.add(diffAmount, currRecord.getDiffAmount());
            }
            if(currRecord.getFeeService()!=null){
                feeService = WeistockUtils.add(feeService, currRecord.getFeeService());
            }
            if(currRecord.getFeeStamp()!=null){
                feeStamp = WeistockUtils.add(feeStamp, currRecord.getFeeStamp());
            }
            afterNumber = currRecord.getAfterNumber();
        }
        summaryDto.setDiffAmount(diffAmount);
        summaryDto.setFeeService(feeService);
        summaryDto.setFeeStamp(feeStamp);
        summaryDto.setAfterNumber(afterNumber);
    }

    @Override
    public List<StockSummaryDto> getStockList() {
        List<StockSummaryDto> stockList = new ArrayList<>();
        stockList.addAll(this.stockMap.values());
        return stockList;
    }

    @Override
    public StockSummaryDto getStockSummary(String stockCode) {
        if(StringUtils.isBlank(stockCode)){
            return null;
        }else{
            return this.stockMap.get(stockCode);
        }
    }

    @Override
    public void updateStockList(List<StockSummaryDto> stockList) {
        this.stockMap.clear();
        for(StockSummaryDto summaryDto : stockList){
            this.stockMap.put(summaryDto.getStockCode(), summaryDto);
        }
    }

    @Override
    public List<StockRecordDto> getRecordList(GetStockRecordRequest queryRequest) {
        List<StockRecordDto> recordList = new ArrayList<>();
        if(StringUtils.isBlank(queryRequest.getStockCode())){
            return recordList;
        }
        StockSummaryDto summaryDto = this.stockMap.get(queryRequest.getStockCode());
        if(summaryDto==null){
            return recordList;
        }

        List<StockRecordDto> dtoList = summaryDto.getRecordList();
        int limit = queryRequest.getLimit();
        // 降序遍历
        for(int i=dtoList.size()-1;i>=0;i--){
            StockRecordDto dto = dtoList.get(i);
            if(!this.filterRecord(dto, queryRequest)){
                recordList.add(dto);
                if(recordList.size()>=limit){
                    break;
                }
            }
        }
        return recordList;
    }

    // 需要过滤的记录，则返回true
    private boolean filterRecord(StockRecordDto recordDto, GetStockRecordRequest request){
        // 日期、时间、委托编号过滤
        if(StringUtils.isNotBlank(request.getDate())
                && StringUtils.isNotBlank(request.getTime())
                && StringUtils.isNotBlank(request.getEntrust())){
            int dataCompare = recordDto.getDate().compareTo(request.getDate());
            // 判断date
            if(dataCompare<0){
                // record date 小，不需要过滤
            }else if(dataCompare>0){
                return true; // record date 大，需要过滤
            }else{
                // 判断time
                int timeCompare = recordDto.getTime().compareTo(request.getTime());
                if(timeCompare<0){
                    // record time 小，不需要过滤
                }else if(timeCompare>0){
                    return true; // record time 大，需要过滤
                }else{
                    // 判断entrustCode
                    int entrustCodeCompare = recordDto.getEntrustCode().compareTo(request.getEntrust());
                    if(entrustCodeCompare>=0){
                        return true; // record entrustCode大，需要过滤
                    }else{
                        // record entrustCode小，不需要过滤
                    }
                }
            }
        }

        return false;
    }
}
